Skip to content

Retry fetch when an idle H2 session socket closes#5388

Closed
marko1olo wants to merge 1 commit into
nodejs:mainfrom
marko1olo:fix-fetch-closed-connection
Closed

Retry fetch when an idle H2 session socket closes#5388
marko1olo wants to merge 1 commit into
nodejs:mainfrom
marko1olo:fix-fetch-closed-connection

Conversation

@marko1olo

Copy link
Copy Markdown
Contributor

Summary

  • retry a fetch network attempt once when the peer closes the connection before response headers are received
  • restrict the retry to replayable/no-body requests and existing transient close errors (ECONNRESET, EPIPE, UND_ERR_SOCKET)
  • add an H2 fetch regression test that closes the idle session socket and verifies a replayed POST body reaches the retried request

Fixes #3492

Tests

  • node --test ./test/fetch/http2.js
  • npm run lint -- lib/web/fetch/index.js test/fetch/http2.js
  • npm run test:h2:fetch
  • git diff --check

Signed-off-by: marko1olo <barsukdana@gmail.com>
@marko1olo marko1olo force-pushed the fix-fetch-closed-connection branch from 0ffdbd8 to f4fbca7 Compare June 8, 2026 02:49
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.82540% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.26%. Comparing base (ee59da3) to head (f4fbca7).

Files with missing lines Patch % Lines
lib/web/fetch/index.js 96.82% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5388   +/-   ##
=======================================
  Coverage   93.25%   93.26%           
=======================================
  Files         110      110           
  Lines       36752    36803   +51     
=======================================
+ Hits        34274    34325   +51     
  Misses       2478     2478           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread lib/web/fetch/index.js
}

if (request.body != null) {
request.body = safelyExtractBody(request.body.source)[0]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this safelyExtractBody call can throw if the body source was already consumed or is not extractable (e.g. a ReadableStream). since we are already inside a catch handler, a throw here would bypass the rest of the error handling and propagate as an unhandled rejection. worth wrapping in a try/catch that falls through to the normal error path.

Comment thread test/fetch/http2.js
for (const socket of sockets) {
socket.destroy()
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

server.close() here is not awaited. the rest of the tests in this file use closeClientAndServerAsPromise which properly waits for the server to close. if the server is still handling connections during teardown this could cause "async activity after test" warnings.

@KhafraDev KhafraDev closed this Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fetch may try to use a closed connection

4 participants